package language.basic;

import org.junit.Test;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class stringTest {

    @Test
    public void stringAPI() {

//        System.out.println(String.format("%23 %04d", 4L));
        String url="https://mobl-test.chinaums.com/ubop_h5/kkfileView/demo/b7f51429aa3783370f699439e20c0c9c%E6%B5%8B%E8%AF%95.docx";
        System.out.println(url.split("")[0]);
        System.out.println(url.substring(0,4));

        int fileUpload = url.lastIndexOf("/");
        String baseUrl = url.substring(0, fileUpload+1); // https://mobl-test.chinaums.com/ubop_h5/kkfileView/demo/
        String fileName = url.substring(fileUpload+1); // b7f51429aa3783370f699439e20c0c9c%E6%B5%8B%E8%AF%95.docx



    }

    @Test
    public void regExpTest(){
        String template = "sdf{{key1}} ,{{key2 }}vc";
        HashMap<String, String> map = new HashMap<>();
        map.put("asdf", "KLK");
        String regExp = "\\{\\{(.*?)\\}\\}";
        Matcher matcher = Pattern.compile(regExp).matcher(template);
        while (matcher.find()) {
            String key = matcher.group(1);
            template = template.replaceFirst(regExp, map.getOrDefault(key.trim(), ""));
        }
        System.out.println(template);


        //匹配中文
        String text = "这是一段中文\n这是另一行aaa\n\n";
        Pattern pattern = Pattern.compile("[\u4e00-\u9fa5]+");
        matcher = pattern.matcher(text);

        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }

    @Test
    public void eq() {
        String s1 = "Programming";
        String s2 = new String("Programming");
        String s3 = "Program";
        String s4 = "ming";
        String s5 = "Program" + "ming";  //这句代码编译器会自动把 “Program” + "ming"优化成“Programming”，所以有s1==s5。
        String s6 = s3 + s4;  //使用StringBuilder.append()创建新对象,这样得到的引用，都要放到内存(堆heap)中保存。
        System.out.println(s1 == s2);  //false
        System.out.println(s1 == s5);  //true
        System.out.println(s1 == s6);  //false
        System.out.println(s1 == s6.intern()); //true String对象的intern方法会得到字符串对象在常量池中对应的版本的引用

        System.out.println(s2 == s2.intern()); //false

    }

    @Test
    public void 反射修改字符串() {
        String s1 = "abcd";
        String s2 = "abcd";
        String s3 = new String("abcd");
        String s4 = new String(s1);
        System.out.println("s1==s2:" + (s1 == s2) + s1.hashCode());
        System.out.println("s1==s3:" + (s1 == s3));
        System.out.println("s3==s4:" + (s3 == s4));
        try {
            Field f = String.class.getDeclaredField("value");
            System.out.print("\nAccessible: " + f.isAccessible());
            f.setAccessible(true);
            System.out.println(" -> " + f.isAccessible());
            char[] v = (char[]) f.get(s1);// 获取S1的内部value数组
            System.out.print("\nvalue:");
            System.out.println(v);
            v[0] = 'x';// 修改数组
            v = new char[1];// 目测因为是get到的是引用的复制，这个引用改变不影响原引用
            v[0] = 'y';
            System.out.print("value:");
            System.out.println(v);

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println("\ns1:" + s1 + "\ns2:" + s2 + "\ns3:" + s3 + "\ns4:" + s4);
        System.out.println("\ns1==s2:" + (s1 == s2) + s1.hashCode());
        System.out.println("s1==s3:" + (s1 == s3));
        System.out.println("s3==s4:" + (s3 == s4));

        //可见，一旦修改了一个String常量的值，所有字符串和它相等的变量的值都会改变，据说是因为它们在底层都是用的同一份数据，没验证。。。
    }



    //字符串的码点、代码单元演示
    @Test
    public void CodePointTest(){
        //大多数常用的码点（字符）用一个代码单元，有些则需要两个代码单元
        String a = "\uD83D\uDE02"; // 😂
        System.out.println(a.length());  //2 length返回代码单元的数量
        System.out.println(a.codePointCount(0, a.length()));  //1 计算码点的数量

        //通过charAt去索引字符串中的每个字符，会出错
        char a1 = a.charAt(0); // \uD83D 乱码 ?
        char a2 = a.charAt(1); // \uDE02 乱码 ?
        System.out.println(a.charAt(0));
        System.out.println(a.charAt(1));

        System.out.println(Character.toChars(a.codePointAt(0)));  //😂  将码点转变为字符

        String b = "\uD842\uDFB7";
        System.out.println(b.length());
    }
}
